package jnpf.onlinedev.util.onlineDevUtil;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import jnpf.base.ActionResult;
import jnpf.base.entity.DictionaryDataEntity;
import jnpf.base.entity.ProvinceEntity;
import jnpf.base.entity.VisualdevEntity;
import jnpf.base.service.DataInterfaceService;
import jnpf.base.service.DictionaryDataService;
import jnpf.base.service.ProvinceService;
import jnpf.base.service.VisualdevService;
import jnpf.util.data.DataSourceContextHolder;
import jnpf.model.FormModel;
import jnpf.model.visiual.JnpfKeyConsts;
import jnpf.model.visiual.OnlineDevData;
import jnpf.model.visiual.fields.FieLdsModel;
import jnpf.onlinedev.model.OnlineDevEnum.CacheKeyEnum;
import jnpf.onlinedev.model.OnlineDevEnum.MultipleControlEnum;
import jnpf.onlinedev.model.OnlineDevEnum.OnlineDataTypeEnum;
import jnpf.onlinedev.model.VisualdevModelDataInfoVO;
import jnpf.onlinedev.service.VisualDevInfoService;
import jnpf.onlinedev.service.VisualdevModelDataService;
import jnpf.permission.service.*;
import jnpf.permission.util.PermissionUtil;
import jnpf.util.DateUtil;
import jnpf.util.JsonUtil;
import jnpf.util.RedisUtil;
import jnpf.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据解析
 *
 * @author JNPF开发平台组
 * @version V3.4.2
 * @copyright 引迈信息技术有限公司（https://www.jnpfsoft.com）
 * @date 2022/7/18
 */
@Slf4j
@Component
public class OnlineSwapDataUtils {
	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private DictionaryDataService dictionaryDataService;
	@Autowired
	private UserService userService;
	@Autowired
	private PositionService positionService;
	@Autowired
	private ProvinceService provinceService;
	@Autowired
	private OrganizeService organizeService;
	@Autowired
	private VisualdevService visualdevService;
	@Autowired
	private VisualdevModelDataService visualdevModelDataService;
	@Autowired
	private DataInterfaceService dataInterfaceService;
	@Autowired
	private VisualDevInfoService visualDevInfoService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private GroupService groupService;


	public List<Map<String, Object>> getSwapList(List<Map<String, Object>> list, List<FieLdsModel> swapDataVoList, String visualDevId, Boolean inlineEdit,List<FormModel> codeList) {
		if (list.isEmpty()) {
			return list;
		}

		//预装数据后直接放入localCache 避免重新取Redis数据大量数据转换耗时
		Map<String, Object> localCache = new HashMap<>();
		Set<String> userList = new HashSet<>();
		Set<String> orgList = new HashSet<>();
		Set<String> posList = new HashSet<>();
		Set<String> allOrgList = new HashSet<>();
		Set<String> roleList = new HashSet<>();
		Set<String> groupList = new HashSet<>();
		localCache.put("__user_list", userList);
		localCache.put("__org_list", orgList);
		localCache.put("__pos_list", posList);
		localCache.put("__allOrg_list", allOrgList);
		localCache.put("__role_list", roleList);
		localCache.put("__group_list", groupList);

		//装填部分数据(用户,组织,岗位,角色)
//		pageIdList(list, swapDataVoList, localCache);

		sysNeedSwapData(swapDataVoList, visualDevId, localCache);

		//redis key
		String dsName = Optional.ofNullable(DataSourceContextHolder.getDatasourceId()).orElse("");
		//组织
		Map<Object, Object> orgMap = redisUtil.getMap(dsName + visualDevId + CacheKeyEnum.ORG.getName());
		orgMap = Optional.ofNullable(orgMap).orElse(new HashMap<>(20));
		//组织需要递归显示
		Map<Object, Object> allOrgMap = redisUtil.getMap(dsName + visualDevId + CacheKeyEnum.AllORG.getName());
		allOrgMap = Optional.ofNullable(allOrgMap).orElse(new HashMap<>(20));
		//岗位
		Map<Object, Object> posMap = redisUtil.getMap(dsName + visualDevId + CacheKeyEnum.POS.getName());
		posMap = Optional.ofNullable(posMap).orElse(new HashMap<>(20));
		//人员
		Map<Object, Object> userMap = redisUtil.getMap(dsName + visualDevId + CacheKeyEnum.USER.getName());
		userMap = Optional.ofNullable(userMap).orElse(new HashMap<>(20));
		//角色
		Map<Object, Object> roleMap = redisUtil.getMap(dsName + visualDevId + CacheKeyEnum.ROLE.getName());
		roleMap = Optional.ofNullable(roleMap).orElse(new HashMap<>(20));
		//分组
		Map<Object, Object> groupMap = redisUtil.getMap(dsName + visualDevId + CacheKeyEnum.GROUP.getName());
		groupMap = Optional.ofNullable(groupMap).orElse(new HashMap<>(20));
		//省市区
		Map<Object, Object> proMap = redisUtil.getMap(String.format("%s-%s-%d",dsName, "province", 1));
		List<Map<String, String>> proMapList = new ArrayList<>();
		if (proMap.size() == 0) {
			proMapList = fillProMap(dsName);
		} else {
			for (int i = 1; i <= 4; i++) {
				String redisKey = String.format("%s-%s-%d", dsName, "province", i);
				proMapList.add(redisUtil.getMap(redisKey));
			}
		}

		localCache.put("__user_map", userMap);
		localCache.put("__org_map", orgMap);
		localCache.put("__pos_map", posMap);
		localCache.put("__allOrg_map", allOrgMap);
		localCache.put("__role_map", roleMap);
		localCache.put("__group_map", groupMap);
		localCache.put("__pro_maplist", proMapList);

		writeRedisAndList(localCache, swapDataVoList, dsName, visualDevId, inlineEdit, list, codeList);
		return list;
	}

	private List<Map<String, Object>> writeRedisAndList(Map<String, Object> localCache, List<FieLdsModel> swapDataVoList, String dsName, String visualDevId, Boolean inlineEdit, List<Map<String, Object>> list, List<FormModel> codeList) {

		Set<String> userList = (Set<String>) localCache.get("__user_list");
		Set<String> orgList = (Set<String>) localCache.get("__org_list");
		Set<String> posList = (Set<String>) localCache.get("__pos_list");
		Set<String> allOrgList = (Set<String>) localCache.get("__allOrg_list");
		Set<String> roleList = (Set<String>) localCache.get("__role_list");

		Map<String, Object> userMap = (Map<String, Object>) localCache.get("__user_map");
		Map<String, Object> orgMap = (Map<String, Object>) localCache.get("__org_map");
		Map<String, Object> posMap = (Map<String, Object>) localCache.get("__pos_map");
		Map<String, Object> allOrgMap = (Map<String, Object>) localCache.get("__allOrg_map");
		Map<String, Object> roleMap = (Map<String, Object>) localCache.get("__role_map");
		Map<String, Object> groupMap = (Map<String, Object>) localCache.get("__group_map");

		List<Map<String, String>> proMapList = (List<Map<String, String>>) localCache.get("__pro_maplist");

		for (FieLdsModel swapDataVo : swapDataVoList) {
			String jnpfKey = swapDataVo.getConfig().getJnpfKey();
			String swapVModel = swapDataVo.getVModel();
			String vModel = inlineEdit ? swapDataVo.getVModel() + "_name" : swapDataVo.getVModel();
			String dataType = swapDataVo.getConfig().getDataType();
			Boolean isMultiple = Objects.nonNull(swapDataVo.getMultiple()) ? swapDataVo.getMultiple() : false;
			for (Map<String, Object> dataMap : list) {
				try {
					Map<String, Object> dataCopyMap = new HashMap<>(dataMap);
					Map<String, Map<String, Object>> dataDetailMap = new HashMap<>();
					if (StringUtil.isEmpty(String.valueOf(dataMap.get(swapVModel))) || String.valueOf(dataMap.get(swapVModel)).equals("[]")
							|| String.valueOf(dataMap.get(swapVModel)).equals("null")) {
						if (jnpfKey.equals(JnpfKeyConsts.CHILD_TABLE)) {
							dataMap.put(vModel, new ArrayList<>());
						} else {
//							dataCopyMap.putAll(dataMap);
							if (inlineEdit) {
								dataMap.put(swapVModel, null);
							}
							dataMap.put(vModel, null);
						}
						continue;
					} else {
						switch (jnpfKey) {
							//公司组件
							case JnpfKeyConsts.COMSELECT:
								//部门组件
							case JnpfKeyConsts.DEPSELECT:
								//所属部门
							case JnpfKeyConsts.CURRDEPT:
								//所属组织
							case JnpfKeyConsts.CURRORGANIZE:
								if (orgMap.size() == 0) {
									orgMap = organizeService.getOrgMap();
									redisUtil.insert(dsName + visualDevId + CacheKeyEnum.ORG.getName(), orgMap, 60 * 5);
								}
								if ("all".equals(swapDataVo.getShowLevel())) {
									//多级组织
									String infoByOrgId = PermissionUtil.getLinkInfoByOrgId(String.valueOf(dataMap.get(swapVModel)), organizeService, false);
									dataMap.put(vModel,infoByOrgId);
								} else {
									dataMap.put(vModel, OnlinePublicUtils.getDataInMethod(orgMap, dataMap.get(swapVModel), isMultiple));
								}
								break;

							//岗位组件
							case JnpfKeyConsts.POSSELECT:
								//所属岗位
							case JnpfKeyConsts.CURRPOSITION:
								if (posMap.size() == 0) {
									posMap = positionService.getPosMap();
									redisUtil.insert(dsName + visualDevId + CacheKeyEnum.POS.getName(), posMap, 60 * 5);
								}
								String posData = OnlinePublicUtils.getDataInMethod(posMap, dataMap.get(swapVModel), isMultiple);
								if (ObjectUtil.isEmpty(dataMap.get(swapVModel))){
									dataMap.put(vModel, " ");
								} else {
									dataMap.put(vModel, posData);
								}
								break;

							//用户组件
							case JnpfKeyConsts.USERSELECT:
								//创建用户
							case JnpfKeyConsts.CREATEUSER:
								//修改用户
							case JnpfKeyConsts.MODIFYUSER:
								if (userMap.size() == 0) {
									userMap = userService.getUserMap();
									redisUtil.insert(dsName + visualDevId + CacheKeyEnum.USER.getName(), userMap, 60 * 5);
								}
								String userData = OnlinePublicUtils.getDataInMethod(userMap, dataMap.get(swapVModel), isMultiple);
								dataMap.put(vModel, userData);
								break;
							//角色选择
							case JnpfKeyConsts.ROLESELECT:
								if (roleMap.size() == 0) {
									roleMap = roleService.getRoleMap();
									redisUtil.insert(dsName + visualDevId + CacheKeyEnum.ROLE.getName(), roleMap, 60 * 5);
								}
								String roleData = OnlinePublicUtils.getDataInMethod(roleMap, dataMap.get(swapVModel), isMultiple);
								dataMap.put(vModel, roleData);
								break;

							case JnpfKeyConsts.GROUPSELECT:
								if (groupMap.size() == 0) {
									groupMap = groupService.getGroupMap();
									redisUtil.insert(dsName + visualDevId + CacheKeyEnum.GROUP.getName(), groupMap, 60 * 5);
								}
								String groupData = OnlinePublicUtils.getDataInMethod(groupMap, dataMap.get(swapVModel), isMultiple);
								dataMap.put(vModel, groupData);
								break;

							//省市区联动
							case JnpfKeyConsts.ADDRESS:
								String addressValue = String.valueOf(dataMap.get(swapVModel));
								if (OnlinePublicUtils.getMultiple(addressValue, MultipleControlEnum.MULTIPLE_JSON_TWO.getMultipleChar())) {
									String[][] data = JsonUtil.getJsonToBean(addressValue, String[][].class);
									List<String> addList = new ArrayList<>();
									for (String[] AddressData : data) {
										List<String> adList = new ArrayList<>();
										for (int i = 0; i < AddressData.length; i++) {
											String addressDatum = AddressData[i];
											String value = String.valueOf(proMapList.get(i).get(addressDatum));
											adList.add(value);
										}
										addList.add(String.join("/", adList));
									}
									dataMap.put(vModel, String.join(";", addList));
								} else if (OnlinePublicUtils.getMultiple(addressValue, MultipleControlEnum.MULTIPLE_JSON_ONE.getMultipleChar())) {
									List<String> proDataS = JsonUtil.getJsonToList(String.valueOf(dataMap.get(swapVModel)), String.class);
									List<String> adList = new ArrayList<>();
									for (int i = 0; i < proDataS.size(); i++) {
										String addressDatum = proDataS.get(i);
										String value = String.valueOf(proMapList.get(i).get(addressDatum));
										adList.add(value);
									}
									dataMap.put(vModel, String.join("/", adList));
								}
								break;
							//开关
							case JnpfKeyConsts.SWITCH:
								String switchValue = String.valueOf(dataMap.get(swapVModel)).equals("1") ? swapDataVo.getActiveTxt() : swapDataVo.getInactiveTxt();
								dataMap.put(vModel, switchValue);
								break;
							//级联
							case JnpfKeyConsts.CASCADER:
								String caslabel = swapDataVo.getProps().getProps().getLabel();
								String casvalue = swapDataVo.getProps().getProps().getValue();
								String casChildren = swapDataVo.getProps().getProps().getChildren();
								String redisKey;
								if (OnlineDataTypeEnum.STATIC.getType().equals(dataType)) {
									redisKey = String.format("%s-%s-%s", visualDevId, swapDataVo.getVModel(), OnlineDataTypeEnum.STATIC.getType());
								} else if (dataType.equals(OnlineDataTypeEnum.DYNAMIC.getType())) {
									redisKey = String.format("%s-%s-%s-%s-%s-%s", dsName, OnlineDataTypeEnum.DYNAMIC.getType(), swapDataVo.getConfig().getPropsUrl(),casvalue,caslabel,casChildren);
								} else {
									redisKey = String.format("%s-%s-%s", dsName, OnlineDataTypeEnum.DICTIONARY.getType(), swapDataVo.getConfig().getDictionaryType());
								}
								Map<String, Object> cascaderMap;
								if (dataType.equals(OnlineDataTypeEnum.DICTIONARY.getType())) {
									List<Map<String, Object>> checkBoxList = (List<Map<String, Object>>) localCache.get(redisKey);
									cascaderMap = OnlinePublicUtils.getDataMap(checkBoxList, swapDataVo);
								} else {
									cascaderMap = (Map<String, Object>) localCache.get(redisKey);
								}
								String s1 = OnlinePublicUtils.getDataInMethod(cascaderMap, dataMap.get(swapVModel), isMultiple);
								dataMap.put(vModel, s1);
								break;
							case JnpfKeyConsts.CHECKBOX:
								String checkBox;
								String checkLabel = swapDataVo.getConfig().getProps().getLabel();
								String checkValue = swapDataVo.getConfig().getProps().getValue();
								if (OnlineDataTypeEnum.STATIC.getType().equals(dataType)) {
									checkBox = String.format("%s-%s-%s", visualDevId, swapDataVo.getVModel(), OnlineDataTypeEnum.STATIC.getType());
								} else if (dataType.equals(OnlineDataTypeEnum.DYNAMIC.getType())) {
									checkBox = String.format("%s-%s-%s-%s-%s", dsName, OnlineDataTypeEnum.DYNAMIC.getType(), swapDataVo.getConfig().getPropsUrl(),checkValue,checkLabel);
								} else {
									checkBox = String.format("%s-%s-%s", dsName, OnlineDataTypeEnum.DICTIONARY.getType(), swapDataVo.getConfig().getDictionaryType());
								}
								Map<String, Object> checkboxMap;
								if (dataType.equals(OnlineDataTypeEnum.DICTIONARY.getType())) {
									List<Map<String, Object>> checkBoxList = (List<Map<String, Object>>) localCache.get(checkBox);
									checkboxMap = OnlinePublicUtils.getDataMap(checkBoxList, swapDataVo);
								} else {
									checkboxMap = (Map<String, Object>) localCache.get(checkBox);
								}
								String s2 = OnlinePublicUtils.getDataInMethod(checkboxMap, dataMap.get(swapVModel), true);
								dataMap.put(vModel, s2);
								break;
							case JnpfKeyConsts.RELATIONFORM:
								//取关联表单数据 按绑定功能加字段区分数据
								redisKey = String.format("%s-%s-%s-%s-%s", dsName, JnpfKeyConsts.RELATIONFORM, swapDataVo.getModelId(), swapDataVo.getRelationField(), dataMap.get(vModel));
								VisualdevModelDataInfoVO infoVO = null;
								if (localCache.containsKey(redisKey) || redisUtil.exists(redisKey)) {
									if (localCache.containsKey(redisKey)) {
										infoVO = (VisualdevModelDataInfoVO) localCache.get(redisKey);
									} else {
										infoVO = JSONObject.parseObject(String.valueOf(redisUtil.getString(redisKey)), VisualdevModelDataInfoVO.class);
										localCache.put(redisKey, infoVO);
									}
								} else {
									VisualdevEntity entity = visualdevService.getInfo(swapDataVo.getModelId());
									String keyId = String.valueOf(dataMap.get(swapVModel));
									if (!StringUtil.isEmpty(entity.getVisualTables()) && !OnlineDevData.TABLE_CONST.equals(entity.getVisualTables())) {
										infoVO = visualDevInfoService.getDetailsDataInfo(keyId, entity);
									} else {
										infoVO = visualdevModelDataService.infoDataChange(keyId, entity);
									}
									redisUtil.insert(redisKey, infoVO, 60 * 5);
									localCache.put(redisKey, infoVO);
								}
								if (infoVO != null) {
									Map<String, Object> formDataMap = JsonUtil.stringToMap(infoVO.getData());
									String relationField = swapDataVo.getRelationField();
									if (formDataMap!=null && formDataMap.size() > 0) {
										dataMap.put(vModel + "_id", dataMap.get(swapVModel));
										dataMap.put(vModel, formDataMap.get(relationField));
										dataDetailMap.put(vModel, formDataMap);
									}
								}
								break;
							case JnpfKeyConsts.POPUPSELECT:
							case JnpfKeyConsts.POPUPTABLESELECT:
								redisKey = String.format("%s-%s-%s-%s-%s", dsName, OnlineDataTypeEnum.DYNAMIC.getType(), swapDataVo.getInterfaceId(), swapDataVo.getPropsValue(), swapDataVo.getRelationField());
								List<Map<String, Object>> mapList = new ArrayList<>();
								Map<String, Object> popMaps = new HashMap<>();
									if (redisUtil.exists(redisKey)){
										popMaps = redisUtil.getMap(redisKey);
									}else {
										ActionResult data =  dataInterfaceService.infoToId(swapDataVo.getInterfaceId(), null, null);;
										if (data != null && data.getData() != null) {
											if (data.getData() instanceof List) {
												mapList = (List<Map<String, Object>>) data.getData();
											}
										}
									}
								String value = String.valueOf(dataMap.get(swapVModel));
								StringJoiner stringJoiner =new StringJoiner(",");
								List<String> popList = new ArrayList<>();
								if (value.startsWith("[")){
									 popList = JsonUtil.getJsonToList(value, String.class);
								} else {
									popList.add(value);
								}
								for (String va : popList){
									if (popMaps.size()>0){
										stringJoiner.add(String.valueOf(popMaps.get(va)));
									}else {
										Map<String, Object> PopMap = mapList.stream().filter(map -> map.get(swapDataVo.getPropsValue()).equals(va)).findFirst().orElse(new HashMap<>());
										if (PopMap.size() > 0) {
											dataMap.put(vModel + "_id", dataMap.get(swapVModel));
											stringJoiner.add(String.valueOf(PopMap.get(swapDataVo.getRelationField())));
											dataDetailMap.put(vModel, PopMap);
										}
									}
								}
								dataMap.put(vModel,String.valueOf(stringJoiner));
								break;
							case JnpfKeyConsts.MODIFYTIME:
							case JnpfKeyConsts.CREATETIME:
							case JnpfKeyConsts.DATE:
								//判断是否为时间戳格式
								String format;
								String dateData = String.valueOf(dataMap.get(swapVModel));
								String dateSwapInfo = swapDataVo.getFormat() != null ? swapDataVo.getFormat() : swapDataVo.getType() != null && swapDataVo.getType().equals(JnpfKeyConsts.DATE) ? "yyyy-MM-dd" : "yyyy-MM-dd HH:mm:ss";
								if (!dateData.contains("-") && !dateData.contains(":") && dateData.length() > 10) {
									DateTimeFormatter ftf = DateTimeFormatter.ofPattern(dateSwapInfo);
									format = ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli((Long) dataMap.get(swapVModel)), ZoneId.of("+8")));
								} else {
									format = dateData;
								}
								if (format.contains(".")) {
									format = format.substring(0, format.lastIndexOf("."));
								}
								SimpleDateFormat sdf = new SimpleDateFormat(dateSwapInfo);
								Date date = sdf.parse(format);
								String outTime = sdf.format(sdf.parse(DateUtil.dateFormat(date)));
								dataMap.put(vModel, outTime);
								break;
							case JnpfKeyConsts.SLIDER:
								dataMap.put(vModel, dataMap.get(vModel) != null ? Integer.parseInt(String.valueOf(dataMap.get(vModel))) : null);
								break;

							case JnpfKeyConsts.UPLOADFZ:
							case JnpfKeyConsts.UPLOADIMG:
								List<Map<String, Object>> fileList = JsonUtil.getJsonToListMap(String.valueOf(dataMap.get(vModel)));
								dataMap.put(vModel, fileList);
								break;
							case JnpfKeyConsts.CHILD_TABLE:
								List<FieLdsModel> children = swapDataVo.getConfig().getChildren();
								List<Map<String, Object>> childList = (List<Map<String, Object>>) dataMap.get(swapDataVo.getVModel());
								List<Map<String, Object>> swapList = getSwapList(childList, children, visualDevId, inlineEdit,codeList);
								dataMap.put(swapDataVo.getVModel(), swapList);
								break;
							default:
								dataMap.put(vModel, dataMap.get(swapVModel));
								break;
						}
						//转换数据接口的数据
						if (dataType != null) {
							String label = swapDataVo.getProps()!=null ? swapDataVo.getProps().getProps().getLabel() : swapDataVo.getConfig().getProps().getLabel();
							String value =  swapDataVo.getProps()!=null ? swapDataVo.getProps().getProps().getValue() : swapDataVo.getConfig().getProps().getValue();
							String children = swapDataVo.getProps()!=null ? Optional.ofNullable(swapDataVo.getProps().getProps().getChildren()).orElse("") : swapDataVo.getConfig().getProps().getChildren();
						 if (swapDataVo.getConfig().getJnpfKey().equals(JnpfKeyConsts.POPUPSELECT) || swapDataVo.getConfig().getJnpfKey().equals(JnpfKeyConsts.POPUPTABLESELECT) ){
								label = swapDataVo.getRelationField();
								value = swapDataVo.getPropsValue();
							}
							if (!jnpfKey.equals(JnpfKeyConsts.CASCADER) && !jnpfKey.equals(JnpfKeyConsts.CHECKBOX)
									&& !jnpfKey.equals(JnpfKeyConsts.POPUPTABLESELECT) && !jnpfKey.equals(JnpfKeyConsts.POPUPSELECT)) {
								//静态数据
								if (dataType.equals(OnlineDataTypeEnum.STATIC.getType())) {
									String redisKey = String.format("%s-%s-%s", visualDevId, swapDataVo.getVModel(), OnlineDataTypeEnum.STATIC.getType());
									Map<String, Object> staticMap = (Map<String, Object>) localCache.get(redisKey);
									String s = OnlinePublicUtils.getDataInMethod(staticMap, dataMap.get(swapVModel), isMultiple);
									dataMap.put(vModel, s);
									//远端数据
								} else if (dataType.equals(OnlineDataTypeEnum.DYNAMIC.getType())) {
									//非级联属性把上一步缓存的接口数据Key的child字段删除
									String redisKey = jnpfKey.equals(JnpfKeyConsts.TREESELECT) ? String.format("%s-%s-%s", dsName, OnlineDataTypeEnum.DYNAMIC.getType(), swapDataVo.getConfig().getPropsUrl())
											: String.format("%s-%s-%s-%s-%s-%s", dsName, OnlineDataTypeEnum.DYNAMIC.getType(), swapDataVo.getConfig().getPropsUrl(), value, label, children);
									Map<String, Object> dynamicMap = (Map<String, Object>) localCache.get(redisKey);
									String s = OnlinePublicUtils.getDataInMethod(dynamicMap, dataMap.get(swapVModel), isMultiple);
									dataMap.put(vModel, s);
									//数据字典
								} else if (dataType.equals(OnlineDataTypeEnum.DICTIONARY.getType())) {
									String redisKey = String.format("%s-%s-%s", dsName, OnlineDataTypeEnum.DICTIONARY.getType(), swapDataVo.getConfig().getDictionaryType());
									Object dicObj = localCache.get(redisKey);
									List<Map<String, Object>> dictionaryList;
									if (dicObj instanceof String) {
										dictionaryList = JsonUtil.getJsonToListMap(String.valueOf(localCache.get(redisKey)));
									} else {
										dictionaryList = (List<Map<String, Object>>) dicObj;
									}
									Map<String, Object> dataInterfaceMap = OnlinePublicUtils.getDataMap(dictionaryList, swapDataVo);
									String s = OnlinePublicUtils.getDataInMethod(dataInterfaceMap, dataMap.get(swapVModel), isMultiple);
									dataMap.put(vModel, s);
								}
							}
						}
					}
					//二维码 条形码最后处理
					swapCodeDataInfo(codeList, dataMap, dataCopyMap);
					//关联选择属性
					if (dataDetailMap.size() > 0) {
						getDataAttr(swapDataVoList, dataMap, dataDetailMap);
					}
				} catch (Exception e) {
					e.printStackTrace();
					log.error("在线开发转换数据错误:" + e.getMessage());
				}
			}
		}
		if (inlineEdit) {
			for (Map<String, Object> map : list) {
				//行内编辑过滤子表
				swapDataVoList = swapDataVoList.stream().filter(s->!s.getVModel().contains("tableField")).collect(Collectors.toList());
				OnlineDevInfoUtils.getInitLineData(swapDataVoList, map);
			}
		}
		return list;
	}

	/**
	 * 取出列表所用到的 用户 组织 岗位的id
	 *
	 * @param list           数据
	 * @param swapDataVoList 控件
	 */
	public static void pageIdList(List<Map<String, Object>> list, List<FieLdsModel> swapDataVoList, Map<String, Object> localCache) {
		Set<String> userList = (Set<String>) localCache.get("__user_list");
		Set<String> orgList = (Set<String>) localCache.get("__org_list");
		Set<String> posList = (Set<String>) localCache.get("__pos_list");
		Set<String> AllOrgList = (Set<String>) localCache.get("__allOrg_list");
		Set<String> roleList = (Set<String>) localCache.get("__role_list");
		for (FieLdsModel swapDataVo : swapDataVoList) {
			String jnpfKey = swapDataVo.getConfig().getJnpfKey();
			String vModel = swapDataVo.getVModel();
			for (Map<String, Object> dataMap : list) {
				if (StringUtil.isEmpty(String.valueOf(dataMap.get(vModel))) || dataMap.get(vModel) == null) {
					continue;
				}
				if (String.valueOf(dataMap.get(vModel)).equals("[]") || String.valueOf(dataMap.get(vModel)).equals("null")) {
					continue;
				} else {
					switch (jnpfKey) {
						//公司组件
						case JnpfKeyConsts.COMSELECT:
							//部门组件
						case JnpfKeyConsts.DEPSELECT:
							//所属部门
						case JnpfKeyConsts.CURRDEPT:
							//所属公司
						case JnpfKeyConsts.CURRORGANIZE:
							if ("all".equals(swapDataVo.getShowLevel())) {
								getIdInMethod(AllOrgList, dataMap.get(vModel));
							} else {
								getIdInMethod(orgList, dataMap.get(vModel));
							}
							break;
						//角色
						case JnpfKeyConsts.ROLESELECT:
							getIdInMethod(roleList, dataMap.get(vModel));
							break;
						//岗位组件
						case JnpfKeyConsts.POSSELECT:
							//所属岗位
						case JnpfKeyConsts.CURRPOSITION:
							getIdInMethod(posList, dataMap.get(vModel));
							break;

						//用户组件
						case JnpfKeyConsts.USERSELECT:
							//创建用户
						case JnpfKeyConsts.CREATEUSER:
							//修改用户
						case JnpfKeyConsts.MODIFYUSER:
							getIdInMethod(userList, dataMap.get(vModel));
							break;
						case JnpfKeyConsts.CHILD_TABLE:
							List<Map<String, Object>> clList = (List<Map<String, Object>>) dataMap.get(vModel);
							List<FieLdsModel> children = swapDataVo.getConfig().getChildren();
							pageIdList(clList, children, localCache);
							break;
						default:
							break;
					}
				}
			}
		}
	}

	/**
	 * 存取对应id集合
	 *
	 * @param idList
	 * @param modelData
	 * @return
	 */
	public static Collection<String> getIdInMethod(Collection<String> idList, Object modelData) {
		if (OnlinePublicUtils.getMultiple(String.valueOf(modelData), MultipleControlEnum.MULTIPLE_JSON_TWO.getMultipleChar())) {
			String[][] data = JsonUtil.getJsonToBean(String.valueOf(modelData), String[][].class);
			for (String[] AddressData : data) {
				for (String s : AddressData) {
					idList.add(s);
				}
			}
		} else if (OnlinePublicUtils.getMultiple(String.valueOf(modelData), MultipleControlEnum.MULTIPLE_JSON_ONE.getMultipleChar())) {
			idList.addAll(JsonUtil.getJsonToList(String.valueOf(modelData), String.class));
		} else {
			String[] modelDatas = String.valueOf(modelData).split(",");
			for (int i = 0; i < modelDatas.length; i++) {
				idList.add(modelDatas[i]);
			}
		}
		return idList;
	}


	/**
	 * 保存需要转换的数据到redis(系统控件)
	 *
	 * @param swapDataVoList
	 * @param visualDevId
	 * @param localCache
	 */
	public void sysNeedSwapData(List<FieLdsModel> swapDataVoList, String visualDevId, Map<String, Object> localCache) {
		//公共数据
		String dsName = Optional.ofNullable(DataSourceContextHolder.getDatasourceId()).orElse("");

		String redisKey;
		try {
			for (FieLdsModel swapDataVo : swapDataVoList) {
				String jnpfKey = swapDataVo.getConfig().getJnpfKey();
				String dataType = swapDataVo.getConfig().getDataType();
				switch (jnpfKey) {
					case JnpfKeyConsts.CHILD_TABLE:
						List<FieLdsModel> children = swapDataVo.getConfig().getChildren();
						sysNeedSwapData(children, visualDevId, localCache);
						break;
					default:
						break;
				}
				if (dataType != null) {
					//数据接口的数据存放
					String label = swapDataVo.getProps()!=null ? swapDataVo.getProps().getProps().getLabel() : swapDataVo.getConfig().getProps().getLabel();
					String value =  swapDataVo.getProps()!=null ? swapDataVo.getProps().getProps().getValue() : swapDataVo.getConfig().getProps().getValue();
					String children = swapDataVo.getProps()!=null ? Optional.ofNullable(swapDataVo.getProps().getProps().getChildren()).orElse("") : swapDataVo.getConfig().getProps().getChildren();
					List<Map<String, Object>> options = new ArrayList<>();
					if (swapDataVo.getConfig().getJnpfKey().equals(JnpfKeyConsts.POPUPSELECT) || swapDataVo.getConfig().getJnpfKey().equals(JnpfKeyConsts.POPUPTABLESELECT) ){
						label = swapDataVo.getRelationField();
						value = swapDataVo.getPropsValue();
					}
					Map<String, String> dataInterfaceMap = new HashMap<>(16);
					String finalValue = value;
					String finalLabel = label;
					//静态数据
					if (dataType.equals(OnlineDataTypeEnum.STATIC.getType())) {
						redisKey = String.format("%s-%s-%s", visualDevId, swapDataVo.getVModel(), OnlineDataTypeEnum.STATIC.getType());
						if (!redisUtil.exists(redisKey)) {
							if (swapDataVo.getOptions() != null) {
								options = JsonUtil.getJsonToListMap(swapDataVo.getOptions());
								JSONArray data = JsonUtil.getListToJsonArray(options);
								getOptions(label, value, children, data, options);
							} else {
								options = JsonUtil.getJsonToListMap(swapDataVo.getSlot().getOptions());
							}

							options.stream().forEach(o -> {
								dataInterfaceMap.put(String.valueOf(o.get(finalValue)), String.valueOf(o.get(finalLabel)));
							});
							redisUtil.insert(redisKey, dataInterfaceMap, 60 * 5);
							if (!localCache.containsKey(redisKey)) {
								localCache.put(redisKey, dataInterfaceMap);
							}
						} else {
							if (!localCache.containsKey(redisKey)) {
								localCache.put(redisKey, redisUtil.getMap(redisKey));
							}
						}
					}
					//远端数据
					if (dataType.equals(OnlineDataTypeEnum.DYNAMIC.getType())) {
						redisKey = jnpfKey.equals(JnpfKeyConsts.TREESELECT) ? String.format("%s-%s-%s", dsName, OnlineDataTypeEnum.DYNAMIC.getType(), swapDataVo.getConfig().getPropsUrl())
								: String.format("%s-%s-%s-%s-%s-%s", dsName, OnlineDataTypeEnum.DYNAMIC.getType(), swapDataVo.getConfig().getPropsUrl(), value, label, children);
						if (!redisUtil.exists(redisKey)) {
							ActionResult data =  dataInterfaceService.infoToId(swapDataVo.getConfig().getPropsUrl(), null, null);
							if (data != null && data.getData() != null) {
								List<Map<String, Object>> dataList = new ArrayList<>();
								if (data.getData() instanceof List) {
//									DataInterfaceActionVo actionVo = (DataInterfaceActionVo) data.getData();
//									if (actionVo.getData() instanceof List) {
										dataList = (List<Map<String, Object>>) data.getData();
//									}
								}
//								else if (data.getData() instanceof List) {
//									dataList = (List<Map<String, Object>>) data.getData();
//								}
								JSONArray dataAll = JsonUtil.getListToJsonArray(dataList);
								treeToList(label, value, children, dataAll, options);
								options.stream().forEach(o -> {
									dataInterfaceMap.put(String.valueOf(o.get(finalValue)), String.valueOf(o.get(finalLabel)));
								});
								redisUtil.insert(redisKey, dataInterfaceMap, 60 * 5);
								if (!localCache.containsKey(redisKey)) {
									localCache.put(redisKey, dataInterfaceMap);
								}
							}
						} else {
							if (!localCache.containsKey(redisKey)) {
								localCache.put(redisKey, redisUtil.getMap(redisKey));
							}
						}
					}
					//数据字典
					if (dataType.equals(OnlineDataTypeEnum.DICTIONARY.getType())) {
						redisKey = String.format("%s-%s-%s", dsName, OnlineDataTypeEnum.DICTIONARY.getType(), swapDataVo.getConfig().getDictionaryType());
						if (!redisUtil.exists(redisKey)) {
							List<DictionaryDataEntity> list = dictionaryDataService.getDicList(swapDataVo.getConfig().getDictionaryType());
							options = list.stream().map(dic -> {
								Map<String, Object> dictionaryMap = new HashMap<>(16);
								dictionaryMap.put("id", dic.getId());
								dictionaryMap.put("enCode", dic.getEnCode());
								dictionaryMap.put("fullName", dic.getFullName());
								return dictionaryMap;
							}).collect(Collectors.toList());
							String dictionaryData = JsonUtil.getObjectToString(options);
							redisUtil.insert(redisKey, dictionaryData, 60 * 5);
							localCache.put(redisKey, options);
						} else {
							if (!localCache.containsKey(redisKey)) {
								String dictionaryStringData = redisUtil.getString(redisKey).toString();
								localCache.put(redisKey, JsonUtil.getJsonToListMap(dictionaryStringData));
							}
						}
					}
				}
			}
		} catch (Exception e) {
			log.error("在线开发转换数据异常:" + e.getMessage());
			e.printStackTrace();
		}
	}


	private List<Map<String, String>> fillProMap(String dsName) {
		List<Map<String, String>> proMapList = new ArrayList<>();
		//分级存储
		for (int i = 1; i <= 4; i++) {
			String redisKey = String.format("%s-%s-%d", dsName, "province", i);
			if (!redisUtil.exists(redisKey)) {
				List<ProvinceEntity> provinceEntityList = provinceService.getProListBytype(String.valueOf(i));
				Map<String, String> provinceMap = new HashMap<>(16);
				provinceEntityList.stream().forEach(p -> provinceMap.put(p.getId(), p.getFullName()));
				proMapList.add(provinceMap);
				redisUtil.insert(redisKey, provinceMap, RedisUtil.CAHCEWEEK);
			}
		}
		return proMapList;
	}

	/**
	 * 级联递归
	 *
	 * @param value
	 * @param label
	 * @param children
	 * @param data
	 * @param result
	 */
	private static void treeToList(String value, String label, String children, JSONArray data, List<Map<String, Object>> result) {
		for (int i = 0; i < data.size(); i++) {
			JSONObject ob = data.getJSONObject(i);
			Map<String, Object> tree = new HashMap<>(16);
			tree.put(value, String.valueOf(ob.get(value)));
			tree.put(label, String.valueOf(ob.get(label)));
			result.add(tree);
			if (ob.get(children) != null) {
				JSONArray childArray = ob.getJSONArray(children);
				treeToList(value, label, children, childArray, result);
			}
		}
	}

	/**
	 * 递归查询
	 *
	 * @param label
	 * @param value
	 * @param Children
	 * @param data
	 * @param options
	 */
	public static void getOptions(String label, String value, String Children, JSONArray data, List<Map<String, Object>> options) {
		for (int i = 0; i < data.size(); i++) {
			JSONObject ob = data.getJSONObject(i);
			Map<String, Object> tree = new HashMap<>(16);
			tree.put(value, String.valueOf(ob.get(value)));
			tree.put(label, String.valueOf(ob.get(label)));
			options.add(tree);
			if (ob.get(Children) != null) {
				JSONArray childrenArray = ob.getJSONArray(Children);
				getOptions(label, value, Children, childrenArray, options);
			}
		}
	}

	/**
	 * 生成关联属性（弹窗选择属性,关联表单属性）
	 *
	 * @param fieLdsModelList
	 * @param dataMap
	 * @param dataDetailMap
	 */
	private static void getDataAttr(List<FieLdsModel> fieLdsModelList, Map<String, Object> dataMap, Map<String, Map<String, Object>> dataDetailMap) {
		for (FieLdsModel fieLdsModel : fieLdsModelList) {
			if (ObjectUtil.isEmpty(fieLdsModel)){
				continue;
			}
			String jnpfKey = fieLdsModel.getConfig().getJnpfKey();
			if (jnpfKey.equals(JnpfKeyConsts.RELATIONFORM_ATTR) || jnpfKey.equals(JnpfKeyConsts.POPUPSELECT_ATTR)) {
				String relationField = fieLdsModel.getRelationField();
				String showField = fieLdsModel.getShowField();
				Map<String, Object> formDataMap = dataDetailMap.get(relationField);
				if (formDataMap!=null){
					dataMap.put(relationField + "_" + showField, formDataMap.get(showField));
				}
			}
		}
	}


	/**
	 * 二维码 条形码详情数据
	 *
	 * @param codeList    控件集合
	 * @param swapDataMap 转换后的数据
	 * @param dataMap     转换前
	 * @return
	 */
	public static void swapCodeDataInfo(List<FormModel> codeList, Map<String, Object> swapDataMap, Map<String, Object> dataMap) {
		for (FormModel formModel : codeList) {
			String jnpfKey = formModel.getConfig().getJnpfKey();
			if (jnpfKey.equals(JnpfKeyConsts.QR_CODE) || jnpfKey.equals(JnpfKeyConsts.BARCODE)) {
				String codeDataType = formModel.getDataType();
				if (OnlineDataTypeEnum.RELATION.getType().equals(codeDataType)) {
					String relationFiled = formModel.getRelationField();
					if (StringUtil.isNotEmpty(relationFiled)) {
						Object relationValue = dataMap.get(relationFiled);
						if (ObjectUtil.isNotEmpty(relationValue)) {
							swapDataMap.put(relationFiled + "_id", relationValue);
						}
					}
				}
			}
		}
	}

	public void clearRedisKey(String visualDevId) {
		List<String> allCacheKey = CacheKeyEnum.getAllCacheKey();
		String dsName = Optional.ofNullable(DataSourceContextHolder.getDatasourceId()).orElse("");
		for (String key : allCacheKey) {
			String cacheKey = dsName + visualDevId + key;
			if (redisUtil.exists(cacheKey)) {
				redisUtil.remove(cacheKey);
			}
		}
	}
}
